/*
 * Copyright 2002-2006 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.tigris.jasmincc.implementation;

import java.util.*;

import org.tigris.jasmincc.framework.*;
import org.tigris.jasmincc.framework.namespace.*;
import org.tigris.mappedlexer.exception.ParseException;
import org.tigris.mappedlexer.validator.VerifyHub;

/**
 * Syntax { A a (m:n); } { ( <identifier> <identifier> '(' <identifier> ':'
 * <identifier> (',' <identifier> ':' <identifier>)* ')'; )* }
 * 
 * @author Sam Huang
 * 
 */
public class InstantaionProduction extends MaplessProductionTemplate {

	protected NamespaceManager namespaceManager = null;

	protected NamingManager namingManager = null;

	protected Coordinator coordinator = null;

	protected Map<String, Object> cache = null;

	@Override
	public void doParse() throws Exception {
		String grammarName;
		String instanceName;
		String qualifiedName;
		String declaredName, assignedName;
		Map<String, String> instances = null;

		namingManager = (NamingManager) cache.get("namingManager");

		tk = lexer.nexttok("{");
		tk = lexer.nexttok();
		while (!tk.equals("}")) {
			grammarName = tk;
			tk = lexer.nexttok(VerifyHub.IDENTIFIER);
			instanceName = tk;

			if (grammarName.equals(instanceName)) {
				throw new Exception("instance name [" + instanceName
						+ "] should NOT be the same as the grammar name ["
						+ grammarName + "].");
			}

			if (namespaceManager.isAnInterface(grammarName)) {
				// it is an interface type
				if (!namingManager.isAnInstance(instanceName)) {
					// TODO how to deal with interfaces
					throw new ParseException("");
				}
			} else {
				qualifiedName = namingManager
						.prefixWithInstanceName(instanceName);
				namingManager.addInstance(instanceName, qualifiedName);

				tk = lexer.nexttok(SYM_LEFT_ROUND_BRACE);
				tk = lexer.nexttok();
				instances = new HashMap<String, String>();
				while (!tk.equals(")")) {
					declaredName = tk;
					tk = lexer.nexttok(":");
					assignedName = lexer.nexttok(VerifyHub.IDENTIFIER);
					String qualifiedAssignedName = namingManager
							.getQualifiedName(assignedName);
					if (qualifiedAssignedName == null) {
						/*
						 * messenger.println("warning: " + "cannot find the
						 * variable: '" + assignedName + "' in grammar '" +
						 * namingManager.getGrammarName() + "'");
						 */
						qualifiedAssignedName = namingManager
								.prefixWithInstanceName(assignedName);
					}
					// TODO is it better to change every '.' to '_' at once?
					// message(String.format("type: %s, value: %s\n",
					// declaredName, assignedName));
					instances.put(declaredName, qualifiedAssignedName);

					tk = lexer.nexttok(",", ")");
					if (tk.equals(",")) {
						tk = lexer.nexttok();
					}
				}
				coordinator.addGrammar(qualifiedName, grammarName, instances);
			}
			tk = lexer.nexttok(";", "}");
			if (tk.equals(";")) {
				tk = lexer.nexttok();
			}
		}
	}

	public void setCache(Map<String, Object> cache) {
		this.cache = cache;
	}

	/**
	 * @param coordinator
	 *            the coordinator to set
	 */
	public void setCoordinator(Coordinator coordinator) {
		this.coordinator = coordinator;
	}

	public void setNamespaceManager(NamespaceManager namespaceManager) {
		this.namespaceManager = namespaceManager;
	}
}
